#ifndef __IO_COMMON_H__
#define __IO_COMMON_H__

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <cast.h>

#define IO_DIR_FILE_SEP '/'
#define META_FILE_EXT ".info"
#define MAX_META_LINE 1024

enum IO_order_type { IO_NATURAL=0 };

typedef short                 IO_type16;
typedef int                   IO_type32;
typedef unsigned int          IO_type32u;
typedef struct { int l[2]; }  IO_type64;

typedef struct {
  IO_type32 coord[1];
} IO_site_order_list;

typedef struct {
  int cycle29;
  int cycle31;
  IO_type32u sum29;
  IO_type32u sum31;
  size_t word_count;
} IO_checksum;

#define IO_MODE_SIZE 8

typedef struct {
  char     filename[FILENAME_MAX];
  char     mode[IO_MODE_SIZE];
  int      swap_bytes;
  time_t   otime;
  FILE*    data_fp;
  FILE*    meta_fp;
  int      data_errno;
  int      meta_errno;
} IO_filehand;

typedef struct {
  char *key;
  char *value;
} IO_meta_item;

typedef struct IO_meta_list_entry_tag {
  IO_meta_item* item;
  int item_was_malloced;
  struct IO_meta_list_entry_tag* last;
  struct IO_meta_list_entry_tag* next;
} IO_meta_list_entry;

typedef struct {
  int length;
  IO_meta_list_entry *head;
  IO_meta_list_entry *tail;
} IO_meta_list;

int IO_open ( IO_filehand* fh, char const* filename, char const* mode );

int IO_close ( IO_filehand* fh );

void IO_swap16 ( IO_type16 *v );
void IO_swap32 ( IO_type32 *v );
void IO_swap64 ( IO_type64 *v );

void IO_CRCsum32_init ( IO_checksum* check, int cycle29, int cycle31 );

void IO_CRCsum32 ( IO_type32u* buffer,
		   size_t buffer_bytes, IO_checksum* check );

int IO_write_checksum ( IO_filehand* fh, IO_checksum* check, int record_num );

int IO_write_meta_item ( IO_filehand* fh, IO_meta_item* entry );

IO_meta_item* IO_read_meta_item ( IO_filehand* fh );

void IO_free_meta_item ( IO_meta_item* item );

void IO_init_meta_list ( IO_meta_list* list );

int IO_append_to_meta_list ( IO_meta_list* list,
			     IO_meta_item* item, int item_was_malloced );

IO_meta_list_entry* IO_meta_first ( IO_meta_list* list );

IO_meta_list_entry* IO_meta_next ( IO_meta_list_entry* entry );

int IO_meta_more ( IO_meta_list_entry* entry );

void IO_get_meta_list ( IO_filehand* fh, IO_meta_list* list );

int IO_put_meta_list ( IO_filehand* fh, IO_meta_list* list );

void IO_free_meta_list ( IO_meta_list* list );


#endif
